﻿
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Drawing.Printing;

namespace Diagram
{
    struct delete_element
    {
        public Figure del_fig;
        public Point location;
        public List<ArrowLine> lines;
    }
    struct add_element
    {
        public Figure add_fig;
        public Point location;

    }
    struct redact_element
    {
        public Figure old_fig;
        public Figure new_fig;
        public Point location;
    }
    struct offset_element
    {
        public Figure off_fig;
        public Point new_location;
        public Point old_location;
    }
    public partial class DiagramBox : UserControl
    {
        bool AltPress = false; // Была ли нажата клавиша АЛТ (1 - была нажата, 0 - не была нажата)
        List<Figure> SelectedFigures = new List<Figure>();
        bool CtrlPress = false;

        cDiagram diagram;
        //выделенная фигура
        Figure selectedFigure = null;
        //фигура или маркер, который тащится мышью
        Figure draggedFigure = null;

        // Координаты точки клика правой кнопкой мыши
        Point pRightMC;

        Figure From = null;
        Figure To = null;
        int fromIndex;
        int toIndex;

        bool EditSterAtr = true;

        //всё необходимое для реализации Undo/ Redo
       // Figure lastDelete = null;

        //история действий пользователя
        // 1 - добавление
        // 2 - удаление
        // 3 - редактирование
        // 4 - перемещение
        List<int> actions = new List<int>();

        List<List<add_element>> add_elements = new List<List<add_element>>();
        List<List<delete_element>> del_elements = new List<List<delete_element>>();
        List<redact_element> red_elements = new List<redact_element>();
        List<List<offset_element>> offset_elements = new List<List<offset_element>>();
        int actionPos = -1;

        int del_pos = -1;
        int addPos = -1;
        int redPos = -1;
        int offPos = -1;

        bool undoRedo = false;
        //int xDel;
        //int yDel;
        Point StartDragLoc;
        int typeLine = 0;
        int typeAtr = 0;

        bool ArrowAddMode = false;
        bool IsArrowAddClicked = false;

        List<Marker> markers = new List<Marker>();
        Pen selectRectPen;
        // Параметры для вставки классов и комментов по нажатию одноименных иконок
        Point StartPoint = new Point(50, 50);
        int Shift = 10;
        Figure AltFigure = null;


        public DiagramBox()
        {
            InitializeComponent();

            DoubleBuffered = true;
            ResizeRedraw = true;

            toolStripButton5.Enabled = true;
            toolStripButton8.Enabled = false;
            toolStripButton9.Enabled = false;
            toolStripButton7.Enabled = false;
            toolStripButton3.Enabled = false;
            toolStripButton2.Enabled = false;
            toolStripButton4.Enabled = false;

            selectRectPen = new Pen(Color.Red, 1);
            selectRectPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
        }
        
        // Сброс настроек при создании новой диаграммы
        public void NewDiagram()
        {
            diagram.figures.Clear();
            actionPos = -1;

            del_pos = -1;
            addPos = -1;
            redPos = -1;
            offPos = -1;

            add_elements.Clear();
            del_elements.Clear();
            red_elements.Clear();
            offset_elements.Clear();

            Invalidate();
            selectedFigure = null;
            draggedFigure = null;
            From = null;
            To = null;
            ArrowAddMode = false;

            StartPoint = new Point(50, 50);
            markers.Clear();

        }
        //диаграмма, отображаемая компонентом
        public cDiagram Diagram
        {
            get { return diagram; }
            set
            {
                diagram = value;
                selectedFigure = null;
                draggedFigure = null;
                markers.Clear();
                Invalidate();
            }
        }
        // Обработка события OnPaint
        protected override void OnPaint(PaintEventArgs e)
        {
            Draw(e.Graphics);
        }

        // Отрисовка содержимого диаграммы
        private void Draw(Graphics gr)
        {
            gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            if (diagram != null)
            {
                //сначала рисуем соединительные линии
                foreach (Figure f in diagram.figures)
                    if (f is LineFigure)
                        f.Draw(gr);
                //затем рисуем плоские фигуры
                foreach (Figure f in diagram.figures)
                    if (f is SolidFigure)
                        f.Draw(gr);
            }

            //рисуем прямоугольник выделенной фигуры
            if (selectedFigure is SolidFigure)
            {
                SolidFigure figure = selectedFigure as SolidFigure;
                RectangleF bounds = figure.Bounds;
                gr.DrawRectangle(selectRectPen, bounds.Left - 2, bounds.Top - 2, bounds.Width + 4, bounds.Height + 4);
            }

            // выделение выбранных фигур


            for (int i = 0; i < SelectedFigures.Count; i++)
            {
                if (!(SelectedFigures[i] is LineFigure))
                {
                    SolidFigure figure1 = SelectedFigures[i] as SolidFigure;
                    RectangleF bounds1 = figure1.Bounds;
                    gr.DrawRectangle(selectRectPen, bounds1.Left - 2, bounds1.Top - 2, bounds1.Width + 4, bounds1.Height + 4);
                }
            }

            // выделение выбранных фигур

            for (int i = 0; i < SelectedFigures.Count; i++)
            {
                if (!(SelectedFigures[i] is LineFigure))
                {
                    SolidFigure figure1 = SelectedFigures[i] as SolidFigure;
                    RectangleF bounds1 = figure1.Bounds;
                    gr.DrawRectangle(selectRectPen, bounds1.Left - 2, bounds1.Top - 2, bounds1.Width + 4, bounds1.Height + 4);
                }
                else
                {
                    LineFigure line = SelectedFigures[i] as LineFigure;
                    line.DrawSelect(gr);
                }
            }


            //рисуем маркеры
            foreach (Marker m in markers)
                m.Draw(gr);

        }

        // Клик мыши произошел на одной из выбранных фигур?
        private bool FindFigureInSelested(Point p)
        {
            //затем ищем среди плоских фигур
            for (int i = 0; i < SelectedFigures.Count; i++)
            {
                if (SelectedFigures[i] is SolidFigure && SelectedFigures[i].IsInsidePoint(p))
                    return true;
            }
            return false;
        }

        public bool activeLines()
        {
            bool active = false;
            int isClass = 0, isComment = 0, isPaket=0;

            foreach (Figure fig in diagram.figures)
            {
                if (fig is ClassFigure)
                    isClass += 1;
                else if (fig is CommentFigure)
                    isComment += 1;
                else if (fig is PaketFigure)
                    isPaket += 1;
            }
            if ((diagram.figures.Count != 0 && isClass >= 2) || (diagram.figures.Count != 0 && isClass >= 1 && isComment >= 1) || (diagram.figures.Count != 0 && isClass >= 1 && isPaket >= 1))
            {
                toolStripButton9.Enabled = true;
                toolStripButton8.Enabled = true;
                toolStripButton7.Enabled = true;
                toolStripButton3.Enabled = true;
                toolStripButton2.Enabled = true;
                toolStripButton4.Enabled = true;
                active = true;
            }
            else
            {
                toolStripButton8.Enabled = false;
                toolStripButton9.Enabled = false;
                toolStripButton7.Enabled = false;
                toolStripButton3.Enabled = false;
                toolStripButton2.Enabled = false;
                toolStripButton4.Enabled = false;
            }
            return active;
        }

        public void Undo()
        {

            undoRedo = true;
            selectedFigure = null;
            if (actionPos != -1)
            {
                if (actions[actionPos] == 1)
                {
                    if (addPos != -1)
                    {
                        for (int k = 0; k < add_elements[addPos].Count(); k++)
                        {
                            if (add_elements[addPos][k].add_fig is SolidFigure)
                            {
                                Figure fig = FindFigureByPoint(add_elements[addPos][k].location);
                                //удаляем фигуру
                                diagram.figures.Remove(fig);
                                //actionPos--;
                                //addPos--;
                            }

                            else if (add_elements[addPos][k].add_fig is ArrowLine)
                            {
                                for (int i = diagram.figures.Count - 1; i >= 0; i--)
                                    if (diagram.figures[i] is ArrowLine)
                                    {
                                        ArrowLine line = (diagram.figures[i] as ArrowLine);
                                        //if ((line.To == (add_elements[addPos].add_fig as LineFigure).To) && (line.From == (add_elements[addPos].add_fig as LineFigure).From))
                                        if (line.ledgePositionX == (add_elements[addPos][k].add_fig as ArrowLine).ledgePositionX)
                                            diagram.figures.RemoveAt(i);
                                    }
                                //actionPos--;
                                //addPos--;
                            }
                        }
                        actionPos--;
                        addPos--;
                    }
                }
                else if (actions[actionPos] == 2)
                {
                    if (del_pos != -1)
                    {
                        if (del_elements[del_pos].Count() == 1)
                        {
                            if (del_elements[del_pos][0].del_fig is ClassFigure)
                            {
                                ClassFigure clF = new ClassFigure();
                                clF = del_elements[del_pos][0].del_fig as ClassFigure;
                                clF.InitializeRect();
                                diagram.figures.Add(clF);
                                clF.location = del_elements[del_pos][0].location;
                                Point res = new Point();
                                for (int j = 0; j < (del_elements[del_pos][0]).lines.Count(); j++)
                                {

                                    ArrowLine line = new ArrowLine();
                                    line = del_elements[del_pos][0].lines[j];
                                    res = FindIndexForLine(line);
                                    if (res.Y == 0)
                                        line.From = clF;
                                    else if (res.X == 0)
                                        line.To = clF;
                                    FindIndexForLine(line);
                                    diagram.figures.Add(line);
                                }
                                actionPos--;
                                del_pos--;

                            }
                            else if (del_elements[del_pos][0].del_fig is CommentFigure)
                            {
                                CommentFigure cmF = new CommentFigure();
                                cmF = del_elements[del_pos][0].del_fig as CommentFigure;
                                diagram.figures.Add(cmF);
                                cmF.location = del_elements[del_pos][0].location;
                                Point res = new Point();
                                for (int j = 0; j < (del_elements[del_pos][0]).lines.Count(); j++)
                                {

                                    ArrowLine line = new ArrowLine();
                                    line = del_elements[del_pos][0].lines[j];
                                    res = FindIndexForLine(line);
                                    if (res.Y == 0)
                                        line.From = cmF;
                                    else if (res.X == 0)
                                        line.To = cmF;
                                    FindIndexForLine(line);
                                    diagram.figures.Add(line);
                                }
                                actionPos--;
                                del_pos--;
                            }
                            else if (del_elements[del_pos][0].del_fig is PaketFigure)
                            {
                                PaketFigure cpF = new PaketFigure();
                                cpF = del_elements[del_pos][0].del_fig as PaketFigure;
                                diagram.figures.Add(cpF);
                                cpF.location = del_elements[del_pos][0].location;
                                Point res = new Point();
                                for (int j = 0; j < (del_elements[del_pos][0]).lines.Count(); j++)
                                {

                                    ArrowLine line = new ArrowLine();
                                    line = del_elements[del_pos][0].lines[j];
                                    res = FindIndexForLine(line);
                                    if (res.Y == 0)
                                        line.From = cpF;
                                    else if (res.X == 0)
                                        line.To = cpF;
                                    FindIndexForLine(line);
                                    diagram.figures.Add(line);
                                }
                                actionPos--;
                                del_pos--;
                            }
                            else if (del_elements[del_pos][0].del_fig is ArrowLine)
                            {
                                ArrowLine line = new ArrowLine();
                                line = del_elements[del_pos][0].del_fig as ArrowLine;
                                FindIndexForLine(line);
                                diagram.figures.Add(line);
                                actionPos--;
                                del_pos--;
                            }
                        }
                        else
                        {
                            //восстанавливаем solidfigures
                            for (int i = 0; i < del_elements[del_pos].Count(); i++)
                            {
                                if (del_elements[del_pos][i].del_fig is ClassFigure)
                                {
                                    ClassFigure clF = new ClassFigure();
                                    clF = del_elements[del_pos][i].del_fig as ClassFigure;
                                    clF.InitializeRect();
                                    diagram.figures.Add(clF);
                                    clF.location = del_elements[del_pos][i].location;
                                    for (int j = 0; j < del_elements[del_pos][i].lines.Count(); j++)
                                    {
                                        if (del_elements[del_pos][i].lines[j].From == del_elements[del_pos][i].del_fig)
                                            del_elements[del_pos][i].lines[j].From = clF;
                                        else if (del_elements[del_pos][i].lines[j].To == del_elements[del_pos][i].del_fig)
                                            del_elements[del_pos][i].lines[j].To = clF;
                                    }

                                }
                                else if (del_elements[del_pos][i].del_fig is CommentFigure)
                                {
                                    CommentFigure cmF = new CommentFigure();
                                    cmF = del_elements[del_pos][i].del_fig as CommentFigure;
                                    diagram.figures.Add(cmF);
                                    cmF.location = del_elements[del_pos][i].location;
                                    for (int j = 0; j < del_elements[del_pos][i].lines.Count(); j++)
                                    {
                                        if (del_elements[del_pos][i].lines[j].From == del_elements[del_pos][i].del_fig)
                                            del_elements[del_pos][i].lines[j].From = cmF;
                                        else if (del_elements[del_pos][i].lines[i].To == del_elements[del_pos][i].del_fig)
                                            del_elements[del_pos][i].lines[j].To = cmF;
                                    }
                                }
                                else if (del_elements[del_pos][i].del_fig is PaketFigure)
                                {
                                    PaketFigure cpF = new PaketFigure();
                                    cpF = del_elements[del_pos][i].del_fig as PaketFigure;
                                    diagram.figures.Add(cpF);
                                    cpF.location = del_elements[del_pos][i].location;
                                    for (int j = 0; j < del_elements[del_pos][i].lines.Count(); j++)
                                    {
                                        if (del_elements[del_pos][i].lines[j].From == del_elements[del_pos][i].del_fig)
                                            del_elements[del_pos][i].lines[j].From = cpF;
                                        else if (del_elements[del_pos][i].lines[j].To == del_elements[del_pos][i].del_fig)
                                            del_elements[del_pos][i].lines[j].To = cpF;
                                    }
                                }
                            }
                            //восстанавливаем линии
                            for (int i = 0; i < del_elements[del_pos].Count(); i++)
                            {
                                if (del_elements[del_pos][i].del_fig is ArrowLine)
                                {
                                    ArrowLine line = new ArrowLine();
                                    line = del_elements[del_pos][i].del_fig as ArrowLine;
                                    FindIndexForLine(line);
                                    diagram.figures.Add(line);
                                }
                                else if (del_elements[del_pos][i].del_fig is SolidFigure)
                                {
                                    bool inList = false;
                                    Point res = new Point();
                                    for (int j = 0; j < del_elements[del_pos][i].lines.Count(); j++)
                                    {
                                        ArrowLine line = new ArrowLine();
                                        line = del_elements[del_pos][i].lines[j];
                                        res = FindIndexForLine(line);
                                        for (int k = diagram.figures.Count - 1; k >= 0; k--)
                                            if (diagram.figures[k] is ArrowLine)
                                                if ((diagram.figures[k] as ArrowLine).fromIndex == line.fromIndex && (diagram.figures[k] as ArrowLine).toIndex == line.toIndex)
                                                    inList = true;
                                        if (!inList)
                                            diagram.figures.Add(line);
                                        //if (res.Y == 0)
                                        //    line.From = clF;
                                        //else if (res.X == 0)
                                        //    line.To = clF;
                                        //FindIndexForLine(line);
                                        inList = false;
                                    }

                                }
                            }
                            actionPos--;
                            del_pos--;
                        }
                    }
                }
                else if (actions[actionPos] == 3)
                {
                    if (redPos != -1)
                    {
                        if (red_elements[redPos].new_fig is SolidFigure)
                        {

                            int n = FindIndexClassByPoint(red_elements[redPos].location);
                            if (diagram.figures[n] is ClassFigure)
                            {

                                (diagram.figures[n] as ClassFigure).copyClass(red_elements[redPos].old_fig as ClassFigure);
                                (diagram.figures[n] as ClassFigure).InitializeRect();

                            }
                            else if (diagram.figures[n] is CommentFigure)
                            {
                                (diagram.figures[n] as CommentFigure).text = (red_elements[redPos].old_fig as CommentFigure).text;

                            }
                            else if (diagram.figures[n] is PaketFigure)
                            {
                                (diagram.figures[n] as PaketFigure).text = (red_elements[redPos].old_fig as PaketFigure).text;

                            }

                            (diagram.figures[n] as SolidFigure).location = red_elements[redPos].location;
                            actionPos--;
                            redPos--;
                        }

                        else if (red_elements[redPos].new_fig is ArrowLine)
                        {

                            for (int i = diagram.figures.Count - 1; i >= 0; i--)
                                if (diagram.figures[i] is LineFigure)
                                {
                                    LineFigure line = (diagram.figures[i] as LineFigure);
                                    if ((line.To == (red_elements[redPos].new_fig as LineFigure).To) && (line.From == (red_elements[redPos].new_fig as LineFigure).From))
                                    {
                                        (diagram.figures[i] as ArrowLine).copyLine(red_elements[redPos].old_fig as ArrowLine);
                                        FindIndexForLine(diagram.figures[i] as ArrowLine);
                                    }
                                }
                            actionPos--;
                            redPos--;
                        }
                    }
                }
                else if (actions[actionPos] == 4)
                {
                    if (offPos != -1)
                    {
                        for (int i = 0; i < offset_elements[offPos].Count; i++)
                        {
                            if (offset_elements[offPos][i].off_fig is SolidFigure && !(offset_elements[offPos][i].off_fig is Marker))
                            {
                                int n = FindIndexClassByPoint(offset_elements[offPos][i].new_location);
                                (diagram.figures[n] as SolidFigure).location = offset_elements[offPos][i].old_location;

                            }
                            else if (offset_elements[offPos][i].off_fig is LedgeMarker)
                            {
                                for (int l = diagram.figures.Count - 1; l >= 0; l--)
                                    if (diagram.figures[l] is ArrowLine && diagram.figures[l].IsInsidePoint(offset_elements[offPos][i].new_location))
                                    {
                                        (diagram.figures[l] as ArrowLine).ledgePositionX = offset_elements[offPos][i].old_location.X;
                                    }
                            }
                        }
                        actionPos--;
                        offPos--;
                    }

                }
                Invalidate();
                activeLines();
                selectedFigure = null;
                draggedFigure = null;
                CreateMarkers();

            }
            undoRedo = false;
        }
        public void Redo()
        {
            undoRedo = true;
            selectedFigure = null;
            if (actionPos != actions.Count() - 1)
            {
                actionPos++;
                if (actions[actionPos] == 1)
                {

                    if (addPos != add_elements.Count() - 1)
                    {
                        addPos++;
                        for (int k = 0; k < add_elements[addPos].Count(); k++)
                        {
                            if (add_elements[addPos][k].add_fig is ClassFigure)
                            {

                                ClassFigure clF = new ClassFigure();
                                clF = add_elements[addPos][k].add_fig as ClassFigure;
                                clF.InitializeRect();
                                diagram.figures.Add(clF);
                                clF.location = add_elements[addPos][k].location;

                            }
                            else if (add_elements[addPos][k].add_fig is CommentFigure)
                            {

                                CommentFigure cmF = new CommentFigure();
                                cmF = add_elements[addPos][k].add_fig as CommentFigure;
                                diagram.figures.Add(cmF);
                                cmF.location = add_elements[addPos][k].location;

                            }
                            else if (add_elements[addPos][k].add_fig is PaketFigure)
                            {
                                PaketFigure cpF = new PaketFigure();
                                cpF = add_elements[addPos][k].add_fig as PaketFigure;
                                diagram.figures.Add(cpF);
                                cpF.location = add_elements[addPos][k].location;

                            }
                            else if (add_elements[addPos][k].add_fig is ArrowLine)
                            {

                                ArrowLine line = new ArrowLine();
                                line.copyLine(add_elements[addPos][k].add_fig as ArrowLine);
                                FindIndexForLine(line);
                                diagram.figures.Add(line);

                            }
                        }

                    }
                }
                else if (actions[actionPos] == 2)
                {

                    if (del_pos != del_elements.Count() - 1)
                    {
                        del_pos++;
                        for (int i = 0; i < del_elements[del_pos].Count(); i++)
                        {
                            if (del_elements[del_pos][i].del_fig is SolidFigure)
                            {

                                Figure fig = FindFigureByPoint(del_elements[del_pos][i].location);


                                //del_elements[del_pos][i].lines.Clear();
                                //удялаем также все линии, ведущие к данной фигуре
                                for (int k = diagram.figures.Count - 1; k >= 0; k--)
                                    if (diagram.figures[k] is ArrowLine)
                                    {
                                        ArrowLine line = (diagram.figures[k] as ArrowLine);
                                        if (line.To == fig || line.From == fig)
                                        {
                                            //del_elements[del_pos][i].lines.Add(line);
                                            diagram.figures.RemoveAt(k);
                                        }
                                    }
                                //удаляем фигуру
                                diagram.figures.Remove(fig);

                            }

                            else if (del_elements[del_pos][i].del_fig is LineFigure)
                            {

                                for (int k = diagram.figures.Count - 1; k >= 0; k--)
                                    if (diagram.figures[k] is LineFigure)
                                    {
                                        LineFigure line = (diagram.figures[k] as LineFigure);
                                        if ((line.To == (del_elements[del_pos][i].del_fig as LineFigure).To) && (line.From == (del_elements[del_pos][i].del_fig as LineFigure).From))
                                            diagram.figures.RemoveAt(k);
                                    }

                            }

                        }

                    }
                }
                else if (actions[actionPos] == 3)
                {

                    if (redPos != red_elements.Count() - 1)
                    {
                        redPos++;
                        if (red_elements[redPos].new_fig is SolidFigure)
                        {

                            int n = FindIndexClassByPoint(red_elements[redPos].location);
                            if (diagram.figures[n] is ClassFigure)
                            {

                                (diagram.figures[n] as ClassFigure).copyClass(red_elements[redPos].new_fig as ClassFigure);
                                (diagram.figures[n] as ClassFigure).InitializeRect();

                            }
                            else if (diagram.figures[n] is CommentFigure)
                            {
                                (diagram.figures[n] as CommentFigure).text = (red_elements[redPos].new_fig as CommentFigure).text;

                            }
                            else if (diagram.figures[n] is PaketFigure)
                            {
                                (diagram.figures[n] as PaketFigure).text = (red_elements[redPos].new_fig as PaketFigure).text;

                            }

                            (diagram.figures[n] as SolidFigure).location = red_elements[redPos].location;

                        }

                        else if (red_elements[redPos].new_fig is ArrowLine)
                        {

                            for (int i = diagram.figures.Count - 1; i >= 0; i--)
                            {
                                if (diagram.figures[i] is LineFigure)
                                {
                                    LineFigure line = (diagram.figures[i] as LineFigure);
                                    if ((line.To == (red_elements[redPos].new_fig as LineFigure).To) && (line.From == (red_elements[redPos].new_fig as LineFigure).From))
                                    {
                                        (diagram.figures[i] as ArrowLine).copyLine(red_elements[redPos].new_fig as ArrowLine);
                                        FindIndexForLine(diagram.figures[i] as ArrowLine);
                                    }
                                }
                            }
                        }
                    }
                }
                else if (actions[actionPos] == 4)
                {
                    if (offPos != offset_elements.Count() - 1)
                    {
                        offPos++;
                        for (int i = 0; i < offset_elements[offPos].Count(); i++)
                        {
                            if (offset_elements[offPos][i].off_fig is SolidFigure && !(offset_elements[offPos][i].off_fig is Marker))
                            {
                                int n = FindIndexClassByPoint(offset_elements[offPos][i].old_location);
                                (diagram.figures[n] as SolidFigure).location = offset_elements[offPos][i].new_location;
                            }
                            else if (offset_elements[offPos][i].off_fig is LedgeMarker)
                            {
                                for (int k = diagram.figures.Count - 1; k >= 0; k--)
                                    if (diagram.figures[k] is ArrowLine && diagram.figures[k].IsInsidePoint(offset_elements[offPos][i].old_location))
                                    {
                                        (diagram.figures[k] as ArrowLine).ledgePositionX = offset_elements[offPos][i].new_location.X;
                                    }
                            }
                        }
                    }
                }
                Invalidate();
                activeLines();
                selectedFigure = null;
                draggedFigure = null;
                CreateMarkers();

            }
            undoRedo = false;
        }
        public Point FindIndexForLine(ArrowLine line)
        {
            Point count = new Point();
            for (int i = diagram.figures.Count - 1; i >= 0; i--)
                if (diagram.figures[i] is SolidFigure)
                {
                    if (line.To == diagram.figures[i])
                    {
                        line.toIndex = i;
                        count.X = 1;
                    }

                    if (line.From == diagram.figures[i])
                    {
                        line.fromIndex = i;
                        count.Y = 1;
                    }
                }
            return count;
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            Focus();
            if (!ArrowAddMode)
            {
                draggedFigure = FindFigureByPoint(e.Location);
                StartDragLoc = e.Location;
                if (e.Button == MouseButtons.Left)
                {
                    if (CtrlPress)
                    {
                        if (draggedFigure != null && !FindFigureInSelested(e.Location))
                        {
                            SelectedFigures.Add(draggedFigure);
                            selectedFigure = null;
                            markers.Clear();
                        }
                        startDragPoint = e.Location;
                    }
                    else
                    {
                        SelectedFigures.Clear();
                        if (!(draggedFigure is Marker))
                        {
                            selectedFigure = draggedFigure;
                            CreateMarkers();
                        }
                        startDragPoint = e.Location;

                    }

                    Invalidate();

                }

                if (e.Button == MouseButtons.Right)
                {
                    if (!(draggedFigure is Marker))
                    {
                        selectedFigure = draggedFigure;
                        CreateMarkers();
                    }

                    SelectedFigures.Clear();

                    Invalidate();

                    pRightMC = new Point(e.X, e.Y);
                    if (selectedFigure == null)
                        cmMain.Show(PointToScreen(e.Location));
                    else
                    {
                        if (selectedFigure is ClassFigure)
                            cmSelectedFigureClass.Show(PointToScreen(e.Location));
                        if (selectedFigure is CommentFigure)
                            cmSelectedFigureComment.Show(PointToScreen(e.Location));
                        if (selectedFigure is LedgeLineFigure)
                            cmSelectedLine.Show(PointToScreen(e.Location));
                        if (selectedFigure is PaketFigure)
                            cmSelectedFigurePaket.Show(PointToScreen(e.Location));
                                     

                    }
                }
               
            }
            else
            {

                if ((FindFigureByPoint(e.Location) is ClassFigure && typeLine != 5) || (FindFigureByPoint(e.Location) is PaketFigure && typeLine != 5) || (FindFigureByPoint(e.Location) is CommentFigure && typeLine == 5))
                {
                    From = FindFigureByPoint(e.Location);
                    fromIndex = FindIndexClassByPoint(e.Location);
                }
            }
        }


        // Обработка двойного клика мыши
        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            base.OnMouseDoubleClick(e);
            // Если есть выбранная фигура и она является "Класс"
            if (selectedFigure != null && (selectedFigure is ClassFigure))
            {
                ClassFigure clF = (selectedFigure as ClassFigure);

                redact_element elem = new redact_element();

                elem.old_fig = new ClassFigure();
                (elem.old_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);

                elem.location = (selectedFigure as ClassFigure).location;

                if (actionPos != actions.Count() - 1)
                {
                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);
                }
                //if (redPos != -1)
                //{
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);
                // }

                // if (addPos != -1)
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                // if (offPos != -1)
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                //if (del_pos != -1)
                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                red_elements.Add(elem);
                actions.Add(3);
                redPos++;
                actionPos++;

                // Создание текстбокса для редактируемого элемента фигуры "Класс"
                TextBox textBox = new TextBox();
                textBox.Parent = this;

                // Определение размеров текстбокса
                Rectangle rect = clF.TextsBounds(new Point(e.X, e.Y));
                textBox.SetBounds(rect.Left, rect.Top, rect.Width, rect.Height);

                // Отображение редактируемого текста
                textBox.Text = clF.Text(new Point(e.X, e.Y));

                // Установка свойств текстбокса
                textBox.Multiline = true;
                textBox.TextAlign = HorizontalAlignment.Center;
                textBox.Focus();
                textBox.LostFocus += new EventHandler(textBox_LostFocus);
            }
            // Если выбранная фигура является фигурой "Связь"
            //if (selectedFigure != null && (selectedFigure is LedgeLineFigure) && typeAtr!=0)
            //{
                //ArrowLine clF = (selectedFigure as ArrowLine);
                //// Создание текстбокса для редактируемого элемента фигуры "Связь"
                //TextBox textBox = new TextBox();
                //textBox.Parent = this;

                //// Определение размеров текстбокса
                ////Rectangle rect = clF.TextsBounds(new Point(e.X, e.Y));
                //int H = 20; int W = 80;
                //Rectangle rect = new Rectangle((int)clF.ledgePositionX, clF.To.location.Y, W, H);
                //textBox.SetBounds(rect.Left, rect.Top, rect.Width, rect.Height);

                //// Отображение редактируемого текста
                //textBox.Text = clF.Text(new Point(e.X, e.Y));

                //// Установка свойств текстбокса
                //textBox.Multiline = true;
                //textBox.TextAlign = HorizontalAlignment.Left;
                //textBox.Focus();
                //textBox.LostFocus += new EventHandler(textBox_LostFocus);


           // }
            // Если выбранная фигура не является фигурой "Класс"
            if (selectedFigure != null && !(selectedFigure is ClassFigure))
            {
                editTextToolStripMenuItem_Click(null, null);
                EditSterAtr = true;
            }
        }

        private void CreateMarkers()
        {
            if (selectedFigure == null)
                markers = new List<Marker>();
            else
            {
                markers = selectedFigure.CreateMarkers(diagram);
                UpdateMarkers();
            }
        }

        private void UpdateMarkers()
        {
            foreach (Marker m in markers)
                if (draggedFigure != m)//маркер который тащится, обновляется сам
                {
                    m.UpdateLocation();
                }
        }

        Point startDragPoint;

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (e.Button == MouseButtons.Left)
            {
                if (CtrlPress)
                {
                    for (int i = 0; i < SelectedFigures.Count; i++)
                    {
                        if (!(SelectedFigures[i] is LineFigure))
                        (SelectedFigures[i] as SolidFigure).Offset(e.Location.X - startDragPoint.X, e.Location.Y - startDragPoint.Y);
                    }
                    Invalidate();

                }
                else
                {
                    if (draggedFigure != null && (draggedFigure is SolidFigure))
                    {
                        (draggedFigure as SolidFigure).Offset(e.Location.X - startDragPoint.X, e.Location.Y - startDragPoint.Y);
                        UpdateMarkers();
                        Invalidate();
                    }
                }
            }
            else
            {
                Figure figure = FindFigureByPoint(e.Location);
                if (figure is Marker)
                    Cursor = Cursors.SizeAll;
                else
                    if (figure != null)
                        Cursor = Cursors.Hand;
                    else
                        Cursor = Cursors.Default;
            }

            startDragPoint = e.Location;
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (!ArrowAddMode)
            {
                if (draggedFigure != null && draggedFigure is SolidFigure && !(draggedFigure is SizeMarker) && !(draggedFigure is EndLineMarker))
                {
                    int xOff = 0, yOff = 0;
                    xOff = e.Location.X - StartDragLoc.X;
                    yOff = e.Location.Y - StartDragLoc.Y;
                    //if ((draggedFigure as SolidFigure).location != startDragPoint)
                    if ((xOff != 0 && yOff == 0) || (xOff == 0 && yOff != 0) || (xOff != 0 && yOff != 0))
                    {
                        List<offset_element> list = new List<offset_element>();
                        if (SelectedFigures.Count() != 0)
                        {
                            for (int i = 0; i < SelectedFigures.Count(); i++)
                            {
                                if (SelectedFigures[i] is SolidFigure)
                                {
                                    offset_element elem = new offset_element();
                                    elem.old_location = new Point((SelectedFigures[i] as SolidFigure).location.X - xOff, (SelectedFigures[i] as SolidFigure).location.Y - yOff);
                                    elem.off_fig = SelectedFigures[i];
                                    elem.new_location = (SelectedFigures[i] as SolidFigure).location;
                                    list.Add(elem);
                                }
                            }
                            if (actionPos != actions.Count() - 1)
                                actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                            offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                            add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                            del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                            red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);

                            offset_elements.Add(list);
                            actions.Add(4);
                            offPos++;
                            actionPos++;
                        }
                        else if (selectedFigure != null && draggedFigure is SolidFigure)
                        {
                            offset_element elem = new offset_element();
                            elem.old_location = new Point((draggedFigure as SolidFigure).location.X - xOff, (draggedFigure as SolidFigure).location.Y - yOff);
                            elem.off_fig = draggedFigure;
                            elem.new_location = (draggedFigure as SolidFigure).location;
                            list.Add(elem);

                            if (actionPos != actions.Count() - 1)
                                actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                            offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                            add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                            del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                            red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);

                            offset_elements.Add(list);
                            actions.Add(4);
                            offPos++;
                            actionPos++;
                        }

                    }

                }


                draggedFigure = null;
                UpdateMarkers();
                Invalidate();
            }
            else
            {
                if ((FindFigureByPoint(e.Location) is ClassFigure) || (FindFigureByPoint(e.Location) is PaketFigure))
                {
                    To = FindFigureByPoint(e.Location);
                    if (From != null && From != To)
                    {
                        ArrowLine line = new ArrowLine();
                        line.From = diagram.figures[fromIndex] as SolidFigure;
                        line.fromIndex = fromIndex;
                        toIndex = FindIndexClassByPoint(e.Location);
                        line.To = diagram.figures[toIndex] as SolidFigure;
                        line.toIndex = toIndex;
                        line.type = typeLine;
                        line.recalc();

                        //EndLineMarker marker = new EndLineMarker(diagram, 1);
                        //marker.location = line.From.location;
                        // marker.location.Offset(0, (int)line.From.Size.Height / 2 + 10);
                        // line.To = marker;
                        diagram.figures.Add(line);

                        List<add_element> list = new List<add_element>();
                        add_element elem = new add_element();
                        elem.add_fig = new ArrowLine();
                        (elem.add_fig as ArrowLine).copyLine(line);

                        if (actionPos != actions.Count() - 1)
                        {

                            actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                        }
                        //if (addPos != -1)
                        add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                        //if (redPos != -1)
                        red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);
                        //if (offPos != -1)
                        offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                        //if (del_pos != -1)
                        del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                        actions.Add(1);
                        list.Add(elem);
                        add_elements.Add(list);
                        addPos++;
                        actionPos++;

                        //selectedFigure = line;
                        //CreateMarkers();
                    }
                    Invalidate();
                    ArrowAddMode = false;
                    if (typeLine == 1)
                    {
                        toolStripButton3.BackColor = Color.White;
                    }
                    else if (typeLine == 2)
                    {
                        toolStripButton7.BackColor = Color.White;
                    }
                    else if (typeLine == 3)
                    {
                        toolStripButton8.BackColor = Color.White;
                    }
                    else if (typeLine == 4)
                    {
                        toolStripButton9.BackColor = Color.White;
                    }
                    else if (typeLine == 5)
                    {
                        toolStripButton2.BackColor = Color.White;
                    }
                    else if (typeLine == 6)
                    {
                        toolStripButton4.BackColor = Color.White;
                    }
                    typeLine = 0;
                    typeAtr = 0;
                    toolStripButton8.Enabled = true;
                    toolStripButton9.Enabled = true;
                    toolStripButton3.Enabled = true;
                    toolStripButton7.Enabled = true;
                    toolStripButton2.Enabled = true;
                    toolStripButton4.Enabled = true;
                    toolStripButton5.Enabled = true;

                    toolStripButton6.Enabled = true;
                    toolStripButton10.Enabled = true;
                    toolStripButton1.Enabled = true;
                    From = null;
                    To = null;

                }
            }
        }
        int FindIndexClassByPoint(Point p)
        {
            int i;
            for (i = diagram.figures.Count - 1; i >= 0; i--)
                if (diagram.figures[i] is SolidFigure && diagram.figures[i].IsInsidePoint(p))
                    return i;
            return i;

        }
        //поиск фигуры, по данной точке
        Figure FindFigureByPoint(Point p)
        {
            //ищем среди маркеров
            foreach (Marker m in markers)
                if (m.IsInsidePoint(p))
                    return m;
            //затем ищем среди плоских фигур
            for (int i = diagram.figures.Count - 1; i >= 0; i--)
                if (diagram.figures[i] is SolidFigure && diagram.figures[i].IsInsidePoint(p))
                    return diagram.figures[i];
            //затем ищем среди линий
            for (int i = diagram.figures.Count - 1; i >= 0; i--)
                if (diagram.figures[i] is LineFigure && diagram.figures[i].IsInsidePoint(p))
                    return diagram.figures[i];
            return null;
        }

        private void miAddRect_Click(object sender, EventArgs e)
        {
            AddFigure<RectFigure>(startDragPoint);
        }

        private void AddFigure<FigureType>(Point location) where FigureType : SolidFigure
        {
            FigureType figure = Activator.CreateInstance<FigureType>();
            figure.location = location;
            if (diagram != null)
                diagram.figures.Add(figure);

            List<add_element> list = new List<add_element>();
            add_element elem = new add_element();
            elem.add_fig = figure;

            if (figure is SolidFigure)
                elem.location = (figure as SolidFigure).location;

            if (actionPos != actions.Count() - 1)
            {

                actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

            }
            // if (addPos != -1)
            add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
            //if (redPos != -1)
            red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);
            // if (offPos != -1)
            offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
            //if (del_pos != -1)
            del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
            actions.Add(1);

            list.Add(elem);
            add_elements.Add(list);
            addPos++;
            actionPos++;

            Invalidate();
        }

        private void editTextToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selectedFigure != null && (selectedFigure is SolidFigure))
            {
                SolidFigure figure = (selectedFigure as SolidFigure);
                TextBox textBox = new TextBox();
                textBox.Parent = this;
                textBox.SetBounds(figure.TextBounds.Left, figure.TextBounds.Top, figure.TextBounds.Width, figure.TextBounds.Height);
                textBox.Text = figure.text;
                textBox.Multiline = true;
                textBox.TextAlign = HorizontalAlignment.Center;
                textBox.Focus();
                textBox.LostFocus += new EventHandler(textBox_LostFocus);

                redact_element elem = new redact_element();
                if (selectedFigure is CommentFigure)
                {

                    elem.old_fig = new CommentFigure();
                    (elem.old_fig as CommentFigure).text = (selectedFigure as CommentFigure).text;

                }
                else if (selectedFigure is PaketFigure)
                {

                    elem.old_fig = new PaketFigure();
                    (elem.old_fig as PaketFigure).text = (selectedFigure as PaketFigure).text;

                }
                elem.location = (selectedFigure as SolidFigure).location;

                if (actionPos != actions.Count() - 1)
                {

                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                }
                //if (redPos != -1)
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);
                //if (addPos != -1)
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                //if (offPos != -1)
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                //if (del_pos != -1)
                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                red_elements.Add(elem);
                actions.Add(3);
                redPos++;
                actionPos++;
                
            }
            if (selectedFigure != null && (selectedFigure is LedgeLineFigure) && typeAtr != 0 && EditSterAtr == false)
            {
                ArrowLine figure = (selectedFigure as ArrowLine);
                TextBox textBox = new TextBox();
                textBox.Parent = this;
                int H = 20; int W = 80;
                Rectangle rect = new Rectangle((int)figure.ledgePositionX, figure.To.location.Y, W, H);
                textBox.SetBounds(rect.Left, rect.Top, rect.Width, rect.Height);
               // textBox.SetBounds(figure.TextBounds.Left, figure.TextBounds.Top, figure.TextBounds.Width, figure.TextBounds.Height);
                if (typeAtr == 1)
                {
                    textBox.Text = figure.stereotype;
                }
                else if (typeAtr == 2)
                {
                    textBox.Text = figure.attribute;
                }
                //else if (typeAtr == 3)
                //{
                //    textBox.Text = figure.multiplicityLeft;
                //}
                //else if (typeAtr == 4)
                //{
                //    textBox.Text = figure.multiplicityRight;
                //}
                textBox.Multiline = true;
                textBox.TextAlign = HorizontalAlignment.Center;
                textBox.Focus();
                textBox.LostFocus += new EventHandler(textBox_LostFocus);
                figure.typeA = typeAtr;
                //diagram.figures.Add(line);

                redact_element elem = new redact_element();
                //ArrowLine line = new ArrowLine();
                elem.old_fig = new ArrowLine();
                (elem.old_fig as ArrowLine).copyLine(selectedFigure as ArrowLine);

                if (actionPos != actions.Count() - 1)
                {

                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                }
                //if (redPos != -1)
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);
                //if (addPos != -1)
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                //if (offPos != -1)
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                //if (del_pos != -1)
                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                red_elements.Add(elem);
                actions.Add(3);
                redPos++;
                actionPos++;
            }

        }

        void textBox_LostFocus(object sender, EventArgs e)
        {
            if (selectedFigure != null && (selectedFigure is ClassFigure))
            {
                TextBox tx = (sender as TextBox);
                (selectedFigure as ClassFigure).SaveText((sender as TextBox).Text, new Point(tx.Location.X + tx.Width / 2, tx.Location.Y + tx.Height / 2));
                redact_element red = new redact_element();

                red = red_elements[redPos];
                red_elements.RemoveAt(redPos);
                red.new_fig = new ClassFigure();
                (red.new_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);

                red_elements.Insert(redPos, red);
          
            }
            if (selectedFigure != null && (selectedFigure is LedgeLineFigure))
            {
                TextBox tx = (sender as TextBox);
                (selectedFigure as ArrowLine).SaveText((sender as TextBox).Text, new Point(tx.Location.X + tx.Width / 2, tx.Location.Y + tx.Height / 2));
                redact_element red = new redact_element();
                red = red_elements[redPos];
                red_elements.RemoveAt(redPos);

                red.new_fig = new ArrowLine();
                (red.new_fig as ArrowLine).copyLine(selectedFigure as ArrowLine);

                red_elements.Insert(redPos, red);
            }
            if (selectedFigure != null && (selectedFigure is SolidFigure) && !(selectedFigure is ClassFigure))
            {
                (selectedFigure as SolidFigure).text = (sender as TextBox).Text;
                redact_element red = new redact_element();
                red = red_elements[redPos];
                red_elements.RemoveAt(redPos);
                if (selectedFigure is CommentFigure)
                {

                    red.new_fig = new CommentFigure();
                    (red.new_fig as CommentFigure).text = (selectedFigure as CommentFigure).text;

                }
                else if (selectedFigure is PaketFigure)
                {

                    red.new_fig = new PaketFigure();
                    (red.new_fig as PaketFigure).text = (selectedFigure as PaketFigure).text;

                }
                red_elements.Insert(redPos, red);
            }
            Controls.Remove((Control)sender);
        }

        private void линияToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selectedFigure != null && (selectedFigure is SolidFigure))
            {
                //LedgeLineFigure line = new LedgeLineFigure();
                ArrowLine line = new ArrowLine();
                line.From = (selectedFigure as SolidFigure);
                EndLineMarker marker = new EndLineMarker(diagram, 1);
                marker.location = line.From.location;
                marker.location.Offset(0, (int)line.From.Size.Height / 2 + 10);
                line.To = marker;
                diagram.figures.Add(line);
                selectedFigure = line;
                CreateMarkers();

                Invalidate();
            }
        }

        private void удалитьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (SelectedFigures.Count() != 0)
            {
                List<delete_element> list = new List<delete_element>();
                for (int i = 0; i < SelectedFigures.Count(); i++)
                {
                    // запоминаем фигуру для отмены

                    delete_element elem = new delete_element();
                    if (SelectedFigures[i] is CommentFigure)
                    {
                        elem.del_fig = new CommentFigure();
                        (elem.del_fig as CommentFigure).text = (SelectedFigures[i] as CommentFigure).text;
                    }
                    else if (SelectedFigures[i] is PaketFigure)
                    {
                        elem.del_fig = new PaketFigure();
                        (elem.del_fig as PaketFigure).text = (SelectedFigures[i] as PaketFigure).text;
                    }
                    else if (SelectedFigures[i] is ClassFigure)
                    {
                        elem.del_fig = new ClassFigure();
                        (elem.del_fig as ClassFigure).copyClass(SelectedFigures[i] as ClassFigure);
                    }
                    else if (SelectedFigures[i] is ArrowLine)
                    {
                        elem.del_fig = new ArrowLine();
                        (elem.del_fig as ArrowLine).copyLine(SelectedFigures[i] as ArrowLine);
                    }
                    if (SelectedFigures[i] is SolidFigure)
                        elem.location = (SelectedFigures[i] as SolidFigure).location;
                    elem.lines = new List<ArrowLine>();
                    for (int k = diagram.figures.Count - 1; k >= 0; k--)
                        if (diagram.figures[k] is LineFigure)
                        {
                            ArrowLine line = (diagram.figures[k] as ArrowLine);
                            if (line.To == SelectedFigures[i] || line.From == SelectedFigures[i])
                            {
                                elem.lines.Add(line);
                                diagram.figures.RemoveAt(k);
                            }
                        }
                    list.Add(elem);

                }
                for (int i = 0; i < list.Count(); i++)
                {
                    for (int k = list[i].lines.Count - 1; k >= 0; k--)
                        for (int m = 0; m < SelectedFigures.Count(); m++)
                        {
                            //определяем чем является данная фигура для линии  
                            if (list[i].lines[k].To == SelectedFigures[m])
                                list[i].lines[k].To = list[m].del_fig as SolidFigure;

                            else if (list[i].lines[k].From == SelectedFigures[m])
                                list[i].lines[k].From = list[m].del_fig as SolidFigure;
                        }

                }

                if (actionPos != actions.Count() - 1)
                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);

                actions.Add(2);
                del_elements.Add(list);
                del_pos++;
                actionPos++;

                //удалем фигуру
                for (int i = 0; i < SelectedFigures.Count(); i++)
                {
                    diagram.figures.Remove(SelectedFigures[i]);
                }
                SelectedFigures.Clear();
            }
            else if (selectedFigure != null)
            {
                List<delete_element> list = new List<delete_element>();
                // запоминаем фигуру для отмены

                delete_element elem = new delete_element();
                if (selectedFigure is CommentFigure)
                {
                    elem.del_fig = new CommentFigure();
                    (elem.del_fig as CommentFigure).text = (selectedFigure as CommentFigure).text;
                }
                else if (selectedFigure is PaketFigure)
                {
                    elem.del_fig = new PaketFigure();
                    (elem.del_fig as PaketFigure).text = (selectedFigure as PaketFigure).text;
                }
                else if (selectedFigure is ClassFigure)
                {
                    elem.del_fig = new ClassFigure();
                    (elem.del_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);
                }
                else if (selectedFigure is ArrowLine)
                {
                    elem.del_fig = new ArrowLine();
                    (elem.del_fig as ArrowLine).copyLine(selectedFigure as ArrowLine);
                }
                if (selectedFigure is SolidFigure)
                    elem.location = (selectedFigure as SolidFigure).location;
                elem.lines = new List<ArrowLine>();
                //удялаем также все линии, ведущие к данной фигуре
                for (int i = diagram.figures.Count - 1; i >= 0; i--)
                    if (diagram.figures[i] is LineFigure)
                    {
                        ArrowLine line = (diagram.figures[i] as ArrowLine);
                        if (line.To == selectedFigure || line.From == selectedFigure)
                        {
                            elem.lines.Add(line);
                            diagram.figures.RemoveAt(i);
                        }
                    }
                list.Add(elem);

                if (actionPos != actions.Count() - 1)
                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);

                actions.Add(2);
                del_elements.Add(list);
                del_pos++;
                actionPos++;

                //удалем фигуру
                diagram.figures.Remove(selectedFigure);
            }
            selectedFigure = null;
            draggedFigure = null;
            CreateMarkers();

            Invalidate();
            activeLines();
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                  удалитьToolStripMenuItem_Click(null, null);
            }

            if (e.Control)
                CtrlPress = true;

            //if ((DiagramBox.ModifierKeys & Keys.Alt) == Keys.Alt)
            if (e.Alt)
            {
                AltPress = true;
                // если есть выбранная фигура
                if (selectedFigure != null && AltFigure == null)
                {
                    if (selectedFigure is CommentFigure)
                    {
                        AltFigure = selectedFigure;

                        CommentFigure Duplicat = new CommentFigure();

                        Duplicat.location = (selectedFigure as CommentFigure).location;
                        Duplicat.text = (selectedFigure as CommentFigure).text;
                        float XComscale = (selectedFigure as CommentFigure).Xscale;
                        float YComscale = (selectedFigure as CommentFigure).Yscale;
                        Duplicat.Scale(XComscale, YComscale);

                        diagram.figures.Add(Duplicat);

                        selectedFigure = Duplicat;

                        Invalidate();
                    }
                    if (selectedFigure is ClassFigure)
                    {
                        AltFigure = selectedFigure;

                        ClassFigure Duplicat1 = new ClassFigure();

                        Duplicat1.location = (selectedFigure as ClassFigure).location;
                        Duplicat1.text = (selectedFigure as ClassFigure).text;
                        //Duplicat1.methods.Clear();
                        //Duplicat1.properties.Clear
                        for (int i = 0; i < (selectedFigure as ClassFigure).properties.Count; i++)
                            Duplicat1.properties.Add((selectedFigure as ClassFigure).properties[i]);
                        for (int i = 0; i < (selectedFigure as ClassFigure).methods.Count; i++)
                            Duplicat1.methods.Add((selectedFigure as ClassFigure).methods[i]);
                        float CXscale = (selectedFigure as ClassFigure).Xscale;
                        float CYscale = (selectedFigure as ClassFigure).Yscale;
                        Duplicat1.Scale(CXscale, CYscale);
                        Duplicat1.Initialize();
                        diagram.figures.Add(Duplicat1);
                        selectedFigure = Duplicat1;
                        Invalidate();
                    }
                    if (selectedFigure is PaketFigure)
                    {
                        AltFigure = selectedFigure;

                        PaketFigure Duplicat2 = new PaketFigure();

                        Duplicat2.location = (selectedFigure as PaketFigure).location;
                        Duplicat2.text = (selectedFigure as PaketFigure).text;
                        float PCXScale = (selectedFigure as PaketFigure).Xscale;
                        float PCYScale = (selectedFigure as PaketFigure).Yscale;
                        Duplicat2.Scale(PCXScale, PCYScale);
                        diagram.figures.Add(Duplicat2);

                        selectedFigure = Duplicat2;

                        Invalidate();
                    }
                }
            }

            base.OnKeyDown(e);
        }
        protected override void OnKeyUp(KeyEventArgs e)
        {
            if (AltPress)
            {
                if (AltFigure != null)
                {
                    // diagram.figures.Remove(AltFigure);

                    AltFigure = null;
                    selectedFigure = null;
                    Invalidate();
                }

                AltPress = false;
            }
            if (CtrlPress)
                CtrlPress = false;
            base.OnKeyUp(e);

        }

        //преобразуем в картинку
        public Bitmap GetImage()
        {
            selectedFigure = null;
            draggedFigure = null;
            CreateMarkers();

            toolStrip1.Hide();
            Bitmap bmp = new Bitmap(Bounds.Width, Bounds.Height);
            DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
            toolStrip1.Show();

            return bmp;
        }

        private void добавитьКлассToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddFigure<ClassFigure>(startDragPoint);
            activeLines();
        }

        private void свойствоToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selectedFigure != null && (selectedFigure is SolidFigure) && (selectedFigure is ClassFigure))
            {
                ClassFigure clF = (ClassFigure)selectedFigure;

                redact_element elem = new redact_element();

                elem.old_fig = new ClassFigure();
                (elem.old_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);


                elem.location = (selectedFigure as ClassFigure).location;

                if (actionPos != actions.Count() - 1)
                {
                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                }

                //if (redPos != -1)
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);

                //if (addPos != -1)
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                //if (offPos != -1)
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                //if (del_pos != -1)
                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                clF.AddProperty();
               
                UpdateMarkers();
                Invalidate();

                elem.new_fig = new ClassFigure();
                (elem.new_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);

                red_elements.Add(elem);
                actions.Add(3);
                redPos++;
                actionPos++;
            }
        }

        private void методToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selectedFigure != null && (selectedFigure is SolidFigure) && (selectedFigure is ClassFigure))
            {
                ClassFigure clF = (ClassFigure)selectedFigure;

                redact_element elem = new redact_element();

                elem.old_fig = new ClassFigure();
                (elem.old_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);


                elem.location = (selectedFigure as ClassFigure).location;

                if (actionPos != actions.Count() - 1)
                {

                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                }
                //if (redPos != -1)
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);

                //if (addPos != -1)
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                //if (offPos != -1)
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                //if (del_pos != -1)
                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                clF.AddMethod();

                UpdateMarkers();
                Invalidate();

                elem.new_fig = new ClassFigure();
                (elem.new_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);
                red_elements.Add(elem);
                actions.Add(3);
                redPos++;
                actionPos++;
            }
        }

        private void добавитьКомментарийToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddFigure<CommentFigure>(startDragPoint);
            activeLines();
            
        }

       
        private void удалитьСвойствоToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selectedFigure != null && (selectedFigure is SolidFigure) && (selectedFigure is ClassFigure))
            {
                ClassFigure clF = (ClassFigure)selectedFigure;
                redact_element elem = new redact_element();

                elem.old_fig = new ClassFigure();
                (elem.old_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);


                elem.location = (selectedFigure as ClassFigure).location;

                if (actionPos != actions.Count() - 1)
                {

                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                }
                //if (redPos != -1)
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);

                //if (addPos != -1)
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                //if (offPos != -1)
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                //if (del_pos != -1)
                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);

                clF.DeleteProperty(pRightMC);//cmSelectedFigureClass.Bounds.Location);

                UpdateMarkers();
                Invalidate();

                elem.new_fig = new ClassFigure();
                (elem.new_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);
                red_elements.Add(elem);
                actions.Add(3);
                redPos++;
                actionPos++;
            }
        }


        private void удалитьМетодToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (selectedFigure != null && (selectedFigure is SolidFigure) && (selectedFigure is ClassFigure))
            {
                ClassFigure clF = (ClassFigure)selectedFigure;

                redact_element elem = new redact_element();
                elem.old_fig = new ClassFigure();
                (elem.old_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);


                elem.location = (selectedFigure as ClassFigure).location;

                if (actionPos != actions.Count() - 1)
                {

                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);

                }
                //if (redPos != -1)
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);

                // if (addPos != -1)
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                //if (offPos != -1)
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                //if (del_pos != -1)
                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                clF.DeleteMethod(pRightMC);//cmSelectedFigureClass.Bounds.Location);

                UpdateMarkers();
                Invalidate();

                elem.new_fig = new ClassFigure();
                (elem.new_fig as ClassFigure).copyClass(selectedFigure as ClassFigure);
                red_elements.Add(elem);
                actions.Add(3);
                redPos++;
                actionPos++;
            }
        }
        //
        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            bool isClass = activeLines();

            if (isClass == true)
            {
                ArrowAddMode = true;
                toolStripButton3.BackColor = Color.BlueViolet;
                typeLine = 1;

                toolStripButton6.Enabled = false;
                toolStripButton5.Enabled = false;
                toolStripButton10.Enabled = false;
                toolStripButton1.Enabled = false;


                toolStripButton8.Enabled = false;
                toolStripButton9.Enabled = false;
                toolStripButton7.Enabled = false;
                toolStripButton2.Enabled = false;
                toolStripButton4.Enabled = false;
            }
        }

        private void toolStripButton7_Click(object sender, EventArgs e)
        {
            bool isClass = activeLines();
            if (isClass == true)
            {
                ArrowAddMode = true;
                toolStripButton7.BackColor = Color.BlueViolet;
                typeLine = 2;
                toolStripButton6.Enabled = false;
                toolStripButton5.Enabled = false;
                toolStripButton10.Enabled = false;
                toolStripButton1.Enabled = false;

                toolStripButton8.Enabled = false;
                toolStripButton9.Enabled = false;
                toolStripButton3.Enabled = false;
                toolStripButton2.Enabled = false;
                toolStripButton4.Enabled = false;
            }
        }

        private void toolStripButton8_Click(object sender, EventArgs e)
        {
            bool isClass = activeLines();

            if (isClass == true)
            {
                ArrowAddMode = true;
                toolStripButton8.BackColor = Color.BlueViolet;
                typeLine = 3;
                toolStripButton6.Enabled = false;
                toolStripButton5.Enabled = false;
                toolStripButton10.Enabled = false;
                toolStripButton1.Enabled = false;

                toolStripButton7.Enabled = false;
                toolStripButton9.Enabled = false;
                toolStripButton3.Enabled = false;
                toolStripButton2.Enabled = false;
                toolStripButton4.Enabled = false;
            }
        }

        private void toolStripButton9_Click(object sender, EventArgs e)
        {
            bool isClass = activeLines();

            if (isClass == true)
            {

                ArrowAddMode = true;
                toolStripButton9.BackColor = Color.BlueViolet;
                typeLine = 4;
                toolStripButton6.Enabled = false;
                toolStripButton5.Enabled = false;
                toolStripButton10.Enabled = false;
                toolStripButton1.Enabled = false;

                toolStripButton8.Enabled = false;
                toolStripButton7.Enabled = false;
                toolStripButton3.Enabled = false;
                toolStripButton2.Enabled = false;
                toolStripButton4.Enabled = false;
            }
            //ArrowDrawInit(4, );
        }

        private void ArrowDrawInit(int pTypeLine, bool b9, bool b8, bool b7, bool b3)
        {
            bool isClass = false;
            foreach (Figure fig in diagram.figures)
            {
                if (fig is ClassFigure)
                    isClass = true;
            }
            if (diagram.figures.Count != 0 && isClass == true)
            {
                ArrowAddMode = true;
                toolStripButton9.BackColor = Color.BlueViolet;
                typeLine = pTypeLine;
                toolStripButton8.Enabled = b8;
                toolStripButton7.Enabled = b7;
                toolStripButton3.Enabled = b3;
            }
            else
            {
                toolStripButton8.Enabled = b8;
                toolStripButton9.Enabled = b9;
                toolStripButton7.Enabled = b7;
                toolStripButton3.Enabled = b3;
            }
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            удалитьToolStripMenuItem_Click(null, null);
        }

        private void toolStripButton10_Click(object sender, EventArgs e)
        {
            Point p = new Point(StartPoint.X + Shift, StartPoint.Y + Shift);
            StartPoint = p;
            AddFigure<CommentFigure>(StartPoint);
            activeLines();
        }

        private void toolStripButton6_Click(object sender, EventArgs e)
        {
            Point p = new Point(StartPoint.X + Shift, StartPoint.Y + Shift);
            StartPoint = p;
            AddFigure<ClassFigure>(StartPoint);
            activeLines();

        }

        private void редактироватьКомментарийToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnMouseDoubleClick(null);
        }

        private void toolStripMenuItem6_Click(object sender, EventArgs e)
        {
            удалитьToolStripMenuItem_Click(sender, e);
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            bool isClass = activeLines();

            if (isClass == true)
            {

                ArrowAddMode = true;
                toolStripButton2.BackColor = Color.BlueViolet;
                typeLine = 5;
                toolStripButton6.Enabled = false;
                toolStripButton5.Enabled = false;
                toolStripButton10.Enabled = false;
                toolStripButton1.Enabled = false;

                toolStripButton8.Enabled = false;
                toolStripButton9.Enabled = false;
                toolStripButton7.Enabled = false;
                toolStripButton3.Enabled = false;
                toolStripButton4.Enabled = false;
            }
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            bool isClass = activeLines();

            if (isClass == true)
            {

                ArrowAddMode = true;
                toolStripButton4.BackColor = Color.BlueViolet;
                typeLine = 6;
                toolStripButton6.Enabled = false;
                toolStripButton5.Enabled = false;
                toolStripButton10.Enabled = false;
                toolStripButton1.Enabled = false;

                toolStripButton8.Enabled = false;
                toolStripButton9.Enabled = false;
                toolStripButton7.Enabled = false;
                toolStripButton3.Enabled = false;
                toolStripButton2.Enabled = false;
            }

        }
 
        private void редактироватьСтереотипToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            if (selectedFigure is LedgeLineFigure)
            {
                typeAtr = 1;
                EditSterAtr = false;
                OnMouseDoubleClick(null);
            }
        }

        private void редактироватьАтрибутToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            if (selectedFigure is LedgeLineFigure)
            {
                typeAtr = 2;
                EditSterAtr = false;
                OnMouseDoubleClick(null);
            }
        }

        //private void редактироватьКратностьToolStripMenuItem_Click(object sender, EventArgs e)
        //{
        //    if (selectedFigure is LedgeLineFigure)
        //    {
        //        typeAtr = 3;
        //        EditSterAtr = false;
        //        OnMouseDoubleClick(null);
        //    }
        //}

        //private void редактироватьКратностьСправаToolStripMenuItem_Click(object sender, EventArgs e)
        //{
        //    if (selectedFigure is LedgeLineFigure)
        //    {
        //        typeAtr = 4;
        //        EditSterAtr = false;
        //        OnMouseDoubleClick(null);
        //    }
        //}

        private void добавитьПакетToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AddFigure<PaketFigure>(startDragPoint);
        }

        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            Point p = new Point(StartPoint.X + Shift, StartPoint.Y + Shift);
            StartPoint = p;
            AddFigure<PaketFigure>(StartPoint);
            activeLines();
        }

        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            удалитьToolStripMenuItem_Click(sender, e);
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            OnMouseDoubleClick(null);
        }

        private void toolStripButton11_Click(object sender, EventArgs e)
        {
            Clipboard.SetDataObject(GetImage());
        }

        private void tBCopy_Click(object sender, EventArgs e)
        {
            // Чистим буфер
            Clipboard.Clear();

            // Копируем выбранные фигуры в буфер
            Clipboard.SetData("List<Figure>", SelectedFigures);

        }

        private void tBPaste_Click(object sender, EventArgs e)
        {
            // Если буфер содержит Список фигур.
            if (Clipboard.ContainsData("List<Figure>"))
            {
                // Очищаем список выбранных фигур в текущей диаграмме
                SelectedFigures.Clear();

                // Достаем из буфера список фигур
                SelectedFigures = Clipboard.GetData("List<Figure>") as List<Figure>;

                List<add_element> list = new List<add_element>();

                // Добавляем фигуры в список фигур текущей диаграммы
                for (int i = 0; i < SelectedFigures.Count; i++)
                {
                    add_element elem = new add_element();
                    elem.add_fig = SelectedFigures[i];
                    if (SelectedFigures[i] is SolidFigure)
                    {
                        elem.location = (SelectedFigures[i] as SolidFigure).location;
                    }
                    list.Add(elem);
                    diagram.figures.Add(SelectedFigures[i]);

                }
                if (actionPos != actions.Count() - 1)
                {
                    actions.RemoveRange(actionPos + 1, actions.Count() - actionPos - 1);
                }
                // if (addPos != -1)
                add_elements.RemoveRange(addPos + 1, add_elements.Count() - addPos - 1);
                //if (redPos != -1)
                red_elements.RemoveRange(redPos + 1, red_elements.Count() - redPos - 1);
                // if (offPos != -1)
                offset_elements.RemoveRange(offPos + 1, offset_elements.Count() - offPos - 1);
                //if (del_pos != -1)
                del_elements.RemoveRange(del_pos + 1, del_elements.Count() - del_pos - 1);
                actions.Add(1);

                add_elements.Add(list);
                addPos++;
                actionPos++;

                // Обновляем картинку
                Invalidate();
            }

        }

        private void tBCut_Click(object sender, EventArgs e)
        {
            // Чистим буфер
            Clipboard.Clear();
            if (SelectedFigures.Count != 0)
            {
                // Копируем выбранные фигуры в буфер
                Clipboard.SetData("List<Figure>", SelectedFigures);
                удалитьToolStripMenuItem_Click(sender, e);
            }

            
            // Очищаем список выбранных фигур в текущей диаграмме
            SelectedFigures.Clear();
            // Обновляем картинку
            Invalidate();

        }


    }
}
